package com.bihu.bihudemo.config;

import com.bihu.bihudemo.auth.UserDetailsServiceImpl;
import com.bihu.bihudemo.auth.compoent.*;
import com.bihu.bihudemo.auth.filter.CaptcherFilter;
import com.bihu.bihudemo.auth.filter.MyOncePerRequestFilter;
import com.bihu.bihudemo.auth.filter.LoginFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.web.cors.CorsUtils;

@Configuration
public class WebSecurityConfig<DynPermissionService> extends WebSecurityConfigurerAdapter {


//    @Autowired
//    @Qualifier("authUserDetailsServiceImpl")
//    UserDetailsService userDetailsService;

    @Autowired
    private MyOncePerRequestFilter myOncePerRequestFilter;
    @Autowired
    CustomLogoutSuccessHandler customLogoutSuccessHandler;

    @Autowired
    private CustomizeSessionInformationExpiredStrategy customizeSessionInformationExpiredStrategy;


    @Autowired
    MyAccessDenyHandler myAccessDenyHandler;

    @Autowired
    MyAuthenticationEntryPoint myAuthenticationEntryPoint;

    @Autowired
    CustomAuthenticationSuccessHandler customAuthenticationSuccessHandler;

    @Autowired
    CustomAuthenticationFailureHandler customAuthenticationFailureHandler;


    /**
     * 自定义验证码拦截器
     */
    @Autowired
    CaptcherFilter captcherFilter;

    @Bean
    public BCryptPasswordEncoder passwordEncoder() {
        // 设置默认的加密方式（强hash方式加密）
        return new BCryptPasswordEncoder();
    }

    @Override
    @Bean
    public UserDetailsService userDetailsService() {
        return new UserDetailsServiceImpl();
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {


        //第1步：解决跨域问题。cors 预检请求放行,让Spring security 放行所有preflight request（cors 预检请求）
        http.authorizeRequests().requestMatchers(CorsUtils::isPreFlightRequest).permitAll();

        //第2步：让Security永远不会创建HttpSession，它不会使用HttpSession来获取SecurityContext
        http.csrf().disable()
//                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
                .headers().cacheControl();


        //放行静态资源
        http.authorizeRequests().antMatchers("/global/**", "/static/**", "/webjars/**", "/swagger-ui.html", "/swagger-resources/*").permitAll();


        //第 5 配置用户的权限（这里最好动态获取用户权限）
        http.authorizeRequests()
                .antMatchers("/login/**", "/", "/cap").permitAll()
//                .anyRequest().access("@DynPermissionService.checkPermission(request,authentication)");
                //发帖，点赞 的功能只有登录之后才有
                .antMatchers("/index", "/comment/like", "/comment/dislike").authenticated();


        //第6 处理非法请求（用户未登录，用户权限不足）
        //AuthenticationEntryPoint 用来解决匿名用户访问无权限资源时的异常
        //AccessDeineHandler 用来解决认证过的用户访问无权限资源时的异常
        http.exceptionHandling()
                .authenticationEntryPoint(myAuthenticationEntryPoint)
                .accessDeniedHandler(myAccessDenyHandler);


        //在用户名认证之前（认证验证码，之前的学习内容），这里是校验token信息，并用户登陆状态保存在Security的上下文
        http.addFilterBefore(myOncePerRequestFilter, UsernamePasswordAuthenticationFilter.class);

        //7 登录方式
//        http.formLogin()
//                .failureHandler(customAuthenticationFailureHandler)
//                .successHandler(customAuthenticationSuccessHandler);

        // 第8步：退出操作
        http.logout()
                .permitAll()
                .logoutSuccessHandler(customLogoutSuccessHandler)
                .deleteCookies("JSESSIONID");

    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService()).passwordEncoder(new BCryptPasswordEncoder());
    }


    @Override
    public void configure(WebSecurity web) throws Exception {
        //将项目中静态资源路径开放出来
        web.ignoring().antMatchers(
                "/config/**", "/css/**",
                "/fonts/**", "/img/**", "/js/**", "/images/**",
                "/static/**",
                "/v2/api-docs",
                "/swagger-resources/configuration/ui",
                "/swagger-resources",
                "/swagger-resources/configuration/security",
                "/swagger-ui.html",
                "/webjars/**");
    }

    /**
     * 手动注册账号、密码拦截器，没起作用
     *
     * @return
     * @throws Exception
     */
    @Bean
    LoginFilter loginFilter() throws Exception {
        LoginFilter filter = new LoginFilter();
        //成功后处理
        filter.setAuthenticationSuccessHandler(customAuthenticationSuccessHandler);
        //失败后处理
        filter.setAuthenticationFailureHandler(customAuthenticationFailureHandler);
        filter.setAuthenticationManager(authenticationManagerBean());
        return filter;
    }


}
